#ifndef Net_IPAddressImpl_INCLUDED
#define Net_IPAddressImpl_INCLUDED


#include "Net.h"
#include "SocketDefs.h"
#include "base/Types/Int.h"
#ifndef PIL_HAVE_ALIGNMENT
#include "base/Types/RefCountedObject.h"
#endif
#include <vector>


namespace pi{


class IPAddressImpl
#ifndef PIL_HAVE_ALIGNMENT
    : public pi::RefCountedObject
#endif
{
public:
    enum Family
        /// Possible address families for IP addresses.
    {
        IPv4
#ifdef PIL_HAVE_IPv6
        ,IPv6
#endif
    };

    virtual ~IPAddressImpl();

    virtual IPAddressImpl* clone() const = 0;
    virtual std::string toString() const = 0;
    virtual pil_socklen_t length() const = 0;
    virtual const void* addr() const = 0;
    virtual Family family() const = 0;
    virtual int af() const = 0;
    virtual pi::UInt32 scope() const = 0;
    virtual bool isWildcard() const	= 0;
    virtual bool isBroadcast() const = 0;
    virtual bool isLoopback() const = 0;
    virtual bool isMulticast() const = 0;
    virtual bool isLinkLocal() const = 0;
    virtual bool isSiteLocal() const = 0;
    virtual bool isIPv4Mapped() const = 0;
    virtual bool isIPv4Compatible() const = 0;
    virtual bool isWellKnownMC() const = 0;
    virtual bool isNodeLocalMC() const = 0;
    virtual bool isLinkLocalMC() const = 0;
    virtual bool isSiteLocalMC() const = 0;
    virtual bool isOrgLocalMC() const = 0;
    virtual bool isGlobalMC() const = 0;
    virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
    virtual unsigned prefixLength() const = 0;

protected:
    IPAddressImpl();

private:
    IPAddressImpl(const IPAddressImpl&);
    IPAddressImpl& operator = (const IPAddressImpl&);
};


//
// IPv4AddressImpl
//

class IPv4AddressImpl: public IPAddressImpl
{
public:
    IPv4AddressImpl();
    IPv4AddressImpl(const void* addr);
    IPv4AddressImpl(unsigned prefix);
    IPv4AddressImpl(const IPv4AddressImpl& addr);
    IPv4AddressImpl& operator = (const IPv4AddressImpl&);
    std::string toString() const;
    pil_socklen_t length() const;
    const void* addr() const;
    Family family() const;
    int af() const;
    unsigned prefixLength() const;
    pi::UInt32 scope() const;
    bool isWildcard() const;
    bool isBroadcast() const;
    bool isLoopback() const;
    bool isMulticast() const;
    bool isLinkLocal() const;
    bool isSiteLocal() const;
    bool isIPv4Compatible() const;
    bool isIPv4Mapped() const;
    bool isWellKnownMC() const;
    bool isNodeLocalMC() const;
    bool isLinkLocalMC() const;
    bool isSiteLocalMC() const;
    bool isOrgLocalMC() const;
    bool isGlobalMC() const;
    static IPv4AddressImpl parse(const std::string& addr);
    void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet);
    IPAddressImpl* clone() const;
    IPv4AddressImpl operator & (const IPv4AddressImpl& addr) const;
    IPv4AddressImpl operator | (const IPv4AddressImpl& addr) const;
    IPv4AddressImpl operator ^ (const IPv4AddressImpl& addr) const;
    IPv4AddressImpl operator ~ () const;
    bool operator == (const IPv4AddressImpl& addr) const;
    bool operator != (const IPv4AddressImpl& addr) const;

private:
    struct in_addr _addr;
};


//
// IPv6AddressImpl
//

class IPv6AddressImpl: public IPAddressImpl
{
public:
    IPv6AddressImpl();
    IPv6AddressImpl(const void* addr);
    IPv6AddressImpl(const void* addr, pi::UInt32 scope);
    IPv6AddressImpl(unsigned prefix);
    std::string toString() const;
    pil_socklen_t length() const;
    const void* addr() const;
    Family family() const;
    int af() const;
    unsigned prefixLength() const;
    pi::UInt32 scope() const;
    bool isWildcard() const;
    bool isBroadcast() const;
    bool isLoopback() const;
    bool isMulticast() const;
    bool isLinkLocal() const;
    bool isSiteLocal() const;
    bool isIPv4Compatible() const;
    bool isIPv4Mapped() const;
    bool isWellKnownMC() const;
    bool isNodeLocalMC() const;
    bool isLinkLocalMC() const;
    bool isSiteLocalMC() const;
    bool isOrgLocalMC() const;
    bool isGlobalMC() const;
    static IPv6AddressImpl parse(const std::string& addr);
    void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet);
    IPAddressImpl* clone() const;
    IPv6AddressImpl operator & (const IPv6AddressImpl& addr) const;
    IPv6AddressImpl operator | (const IPv6AddressImpl& addr) const;
    IPv6AddressImpl operator ^ (const IPv6AddressImpl& addr) const;
    IPv6AddressImpl operator ~ () const;
    bool operator == (const IPv6AddressImpl& addr) const;
    bool operator != (const IPv6AddressImpl& addr) const;
    IPv6AddressImpl(const IPv6AddressImpl& addr);
    IPv6AddressImpl& operator = (const IPv6AddressImpl&);

private:
    struct in6_addr _addr;
    unsigned int    _scope;
};


} // namespace pi


#endif // Net_IPAddressImpl_INCLUDED
